<template>
  <!-- , top: top + 'px'  -->
  <view :style="{ zIndex: zIndex }" class="-message-container">
    <block v-for="message in messageQueue" :key="message.id">
      <view
        :class="[message.animation, backgroundClass(message)]"
        class="message"
        :key="message.id"
      >
        <!-- <label
          v-if="message.type === 'info'"
          class="bm-icon info iconfont icon_warn_fill"
        ></label>
        <label
          v-if="message.type === 'success'"
          class="bm-icon success iconfont success-fill"
        ></label>
        <label
          v-if="message.type === 'warn'"
          class="bm-icon warn iconfont icon_warn_fill"
        ></label>
        <label
          v-if="message.type === 'error'"
          class="bm-icon error iconfont icon_roundclose_fill"
        ></label> -->
        <label>{{ message.message }}</label>
      </view>
    </block>
  </view>
</template>

<script>
// 需要支持的单独配置项：显示时长、是否启用背景、类型、内容
import { types } from "@/utils/index";
const system = uni.getSystemInfoSync();

export default {
  name: "wyx-message",
  props: {
    zIndex: {
      type: Number,
      default: 10000,
    },
    duration: {
      type: Number,
      default: 2000,
    },
    background: {
      type: Boolean,
      default: false,
    },
    top: {
      default: (system.safeArea ? system.safeArea.top : 44) + 24,
    },
  },
  data() {
    return {
      messageQueue: [],
      lastId: 0,
    };
  },
  computed: {
    backgroundClass() {
      return (msg) => {
        return this.background || msg.background
          ? `background-${msg.type}`
          : "";
      };
    },
  },
  methods: {
    /**
     * 展示普通提示信息
     * @param {Object} message
     */
    info(arg) {
      const message = {
        type: "info",
      };
      if (typeof arg === "object" && arg) {
        message.message = arg.message;
        message.duration = arg.duration;
        message.background = arg.background;
      } else if (typeof arg === "string") {
        message.message = arg;
      }
      return this.fadeIn(message);
    },
    /**
     * 展示成功提示
     * @param {Object} message
     */
    success(arg) {
      const message = {
        type: "success",
      };
      if (typeof arg === "object" && arg) {
        message.message = arg.message;
        // 显示时长会用在 settimeout的参数中，必须保证类型正确
        if (
          arg.duration &&
          typeof arg.duration === "number" &&
          arg.duration >= 0
        ) {
          message.duration = arg.duration;
        }
        message.background = arg.background;
      } else if (typeof arg === "string") {
        message.message = arg;
      }
      return this.fadeIn(message);
    },
    /**
     * 展示警告提示
     */
    warning(arg) {
      const message = {
        type: "warn",
      };
      if (typeof arg === "object" && arg) {
        message.message = arg.message;
        if (
          arg.duration &&
          typeof arg.duration === "number" &&
          arg.duration >= 0
        ) {
          message.duration = arg.duration;
        }
        message.background = arg.background;
      } else if (typeof arg === "string") {
        message.message = arg;
      }
      return this.fadeIn(message);
    },
    /**
     * 展示错误提示
     * @param {Object} message
     */
    error(arg) {
      const message = {
        type: "error",
      };
      if (typeof arg === "object" && arg) {
        message.message = arg.message;
        if (
          arg.duration &&
          typeof arg.duration === "number" &&
          arg.duration >= 0
        ) {
          message.duration = arg.duration;
        }
        message.background = arg.background;
      } else if (typeof arg === "string") {
        message.message = arg;
      }
      return this.fadeIn(message);
    },
    fadeIn(message) {
      return uni.showToast({
        title: message.message,
        icon: "none",
        duration: 2000,
      });
      return new Promise((resolve) => {
        message.id = this.generateId();
        message.animation = "fadeIn";
        this.messageQueue.push(message);
        // 动画执行完毕后取消动画效果，防止列表刷新时重新执行动画
        setTimeout(() => {
          message.animation = "";
        }, 410);
        // 显示一段时间后隐藏
        setTimeout(() => {
          this.fadeOut(message);
          if (typeof message.complete === "function") {
            message.complete();
          }
          if (typeof message.success === "function") {
            message.success();
          }
          resolve();
        }, message.duration || this.duration);
      });
    },
    fadeOut(message) {
      message.animation = "fadeOut";
      setTimeout(() => {
        let idx = 0;
        this.messageQueue.some((msg, index) => {
          if (msg.id === message.id) {
            idx = index;
            if (types.isFunction(message.onClose)) {
              message.onClose();
            }
            return true;
          }
        });
        this.messageQueue.splice(idx, 1);
      }, 500);
    },
    generateId() {
      return new Date().getTime() * 1000 + (this.lastId++ % 1000);
    },
  },
};
</script>

<style lang="scss" scoped>
@import "./iconfont.css";

.-message-container {
  display: flex;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  /* top: calc(var(--window-top) + 48rpx); */
  top: calc(var(--window-top) + 60rpx);
  min-width: 10rpx;
  max-width: 550rpx;
  height: 300rpx;
  position: fixed;
  margin: auto;
  flex-direction: column;
  align-items: center;
  // 透明层允许点击穿透
  pointer-events: none;

  .message {
    display: flex;
    // 内容区域禁止点击穿透
    pointer-events: all;
    align-items: center;
    padding: 16rpx 32rpx;
    border-radius: 4px;
    margin-top: 10rpx;
    min-height: 80rpx;
    /* box-shadow: 0 1rpx 12rpx rgba(0, 0, 0, 0.2); */
    /* background: #fff; */
    background: rgba(0, 0, 0, 0.7);
    color: #fff;
    min-height: 74rpx;
    transition: all 0.5s;
    box-sizing: border-box;
    /* font-size: 32rpx; */
    font-size: 28rpx;
    label {
      font-size: 32rpx;
    }
    .bm-icon {
      margin-right: 10rpx;
    }

    .info {
      color: #288ced;
    }

    .success {
      color: #09be70;
    }

    .warn {
      color: #ff991f;
    }

    .error {
      color: #ef4017;
    }
  }
  .background {
    border: 2rpx solid transparent;
    box-shadow: none !important;
    &-info {
      border-color: #d4eefe;
      background: #f0faff;
      color: #288ced;
    }

    &--success {
      border-color: #baf2d1;
      background: #edfff4;
      color: #09be70;
    }

    &-warn {
      border-color: #ffe7a7;
      background: #fff9e7;
      color: #ff991f;
    }

    &-error {
      border-color: #ffcfb9;
      background: #ffefe6;
      color: #ef4017;
    }
  }

  .fadeIn {
    animation: fadeIn 0.4s both;
  }

  @keyframes fadeIn {
    from {
      opacity: 0;
      transform: translate(0, -60rpx);
    }

    to {
      opacity: 1;
      transform: translate(0, 0);
    }
  }

  .fadeOut {
    animation: fadeOut 0.4s forwards;
  }

  @keyframes fadeOut {
    from {
      opacity: 1;
      transform: translate(0, 0);
    }

    to {
      opacity: 0;
      margin-top: -74rpx;
    }
  }
}
</style>
